﻿using LeRenard.Libraries.PlatformInspection.InfoNodes;
using System;
using System.Collections.Generic;
namespace LeRenard.Libraries.PlatformInspection.Inspectors
{
    /// <summary>
    /// Defines a part of code used by a given <see cref="IInspector"/>.
    /// </summary>
    /// <typeparam name="TInspector">The type of the <see cref="IInspector"/> this module belongs to.</typeparam>
    public abstract class InspectorModule<TInspector> : IInspectorModule<TInspector>
    {
        #region Construction
        /// <summary>
        /// Initializes a new <see cref="InspectorModule"/>.
        /// </summary>        
        public InspectorModule(string name)
        {
            ThrowIf.NullOrEmpty(() => name);

            _name = name;
            _exceptions = new List<Exception>();
        }
        #endregion

        #region IInspectorModule
        /// <summary>
        /// Gets the type of <see cref="IInspector"/> this module belongs to.
        /// </summary>
        public Type InspectorType { get { return typeof(TInspector); } }

        /// <summary>
        /// Gets the module name.
        /// </summary>
        public string Name { get { return _name; } }
        private readonly string _name;

        /// <summary>
        /// Gets the information this module gathers.
        /// </summary>        
        public InfoNode GetInformation()
        {
            var rootNode = new InfoNode(name: Name, displayStrategy: InfoNodeEmptyValueDisplayStrategy.TreatAsTitleInfoNode);

            try
            {                
                var infoNodes = GetInformationImpl();
                rootNode.AddInfoNodes(infoNodes);

                return rootNode;
            }
            catch (Exception ex)
            {
                _exceptions.Add(ex);
                return rootNode;
            }
        }

        /// <summary>
        /// Implementation of the information this module gathers.
        /// </summary>
        protected abstract IEnumerable<InfoNode> GetInformationImpl();

        /// <summary>
        /// Gets the exceptions occured during the last call of <see cref="GetInformation"/>.
        /// </summary>        
        public IEnumerable<Exception> Exceptions { get { return _exceptions; } }
        protected List<Exception> _exceptions;
        #endregion
    }
}
